<!-- 表单组件 -->
<template>
  <el-form ref="ruleFormRef" :model="ruleForm" :rules="formData.rules" label-width="120px" :size="formData.size">
    <div v-for="(item, index) in formData.formItem">
      <el-form-item :key="index" :label="item.label" :prop="item.key"
        v-if="item.hide && item.hide(ruleForm) || !item.hide">
        <el-input v-if="item.styleType == 'input'" v-model="ruleForm[item.key]" :placeholder="item.placeholder"
          :disabled="loading || isLook" :type="item.type" show-word-limit :maxlength="item.length" />
        <el-input v-if="item.styleType == 'inputDis'" v-model="ruleForm[item.key]" :placeholder="item.placeholder"
          :disabled="item.disabled" :type="item.type" />
        <el-select v-if="item.styleType == 'select' && (item.hide && item.hide(ruleForm) || !item.hide)"
          v-model="ruleForm[item.key]" :placeholder="item.placeholder" :disabled="loading || isLook"
          :multiple="item.type">
          <el-option :label="v.label" :value="v.value" v-for="v in item.data" :index="v.value" />
        </el-select>
        <el-select v-if="item.styleType == 'selectDis' && (item.hide && item.hide(ruleForm) || !item.hide)"
          v-model="ruleForm[item.key]" :placeholder="item.placeholder" :disabled="item.disabled" :multiple="item.type">
          <el-option :label="v.label" :value="v.value" v-for="v in item.data" :index="v.value" />
        </el-select>
        <el-date-picker v-if="item.styleType == 'date' && item.type !== 'daterange'" v-model="ruleForm[item.key]"
          :type="item.type" :format="item.format" :disabled="loading || isLook" :placeholder="item.placeholder"
          :value-format="item.valueFormat" />
        <el-date-picker v-if="item.styleType == 'date' && item.type === 'daterange'" v-model="ruleForm[item.key]"
          :type="item.type" :format="item.format" :disabled="loading || isLook"
          :start-placeholder="item.startPlaceholder" :end-placeholder="item.endPlaceholder"
          :value-format="item.valueFormat" />
        <el-time-select v-if="item.styleType == 'time'" v-model="ruleForm[item.key]" :format="item.format"
          :start="item.start" :step="item.step" :end="item.end" :disabled="loading || isLook"
          :placeholder="item.placeholder" />
        <el-switch v-if="item.styleType == 'switch'" v-model="ruleForm[item.key]" :disabled="loading || isLook" />
        <el-checkbox-group v-if="item.styleType == 'checkbox'" v-model="ruleForm[item.key]"
          :disabled="loading || isLook">
          <el-checkbox :label="v.value" v-for="v in item.data">{{ v.label }}</el-checkbox>
        </el-checkbox-group>
        <el-radio-group v-if="item.styleType == 'radio'" v-model="ruleForm[item.key]" :disabled="loading || isLook">
          <el-radio :label="v.value" v-for="v in item.data">{{ v.label }}</el-radio>
        </el-radio-group>
        <el-upload class="my-upload" :action="item.action" :disabled="loading || isLook" v-loading="uploadLoading"
          :name="item.name" :show-file-list="false"
          :on-success="(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => onSuccess(response, uploadFile, uploadFiles, item)"
          :before-upload="beforeAvatarUpload" :accept="item.accept" v-if="item.styleType == 'upload' && item.action">
          <img v-if="ruleForm[item.key]" :src="ruleForm[item.key]" class="my-upload__img" />
          <div class="my-upload__bg" v-if="ruleForm[item.key]">
            <el-icon :size="24" @click.stop="onPreview(ruleForm[item.key])">
              <zoom-in />
            </el-icon>
            <el-icon :size="24" @click.stop="onDelete(item)" v-if="!loading && !isLook">
              <Delete />
            </el-icon>
          </div>
          <el-icon v-else class="avatar-uploader-icon" :size="35" color="#999">
            <Plus />
          </el-icon>
        </el-upload>
        <div v-if="item.styleType == 'uploads' && item.action" style="display: flex;">
          <div v-if="ruleForm[item.key]" style="display: flex;">
            <div class="my-upload" v-for="(t, inx) in ruleForm[item.key]">
              <img :src="t" class="my-upload__img" />
              <div class="my-upload__bg">
                <el-icon :size="22" @click.stop="onPreview(ruleForm[item.key])">
                  <zoom-in />
                </el-icon>
                <el-icon :size="22" @click.stop="onDelete(item, inx)" v-if="!loading && !isLook">
                  <Delete />
                </el-icon>
              </div>
            </div>
          </div>
          <el-upload class="my-upload" :action="item.action" :disabled="loading || isLook" v-loading="uploadLoading"
            :name="item.name" :show-file-list="false"
            :on-success="(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => onSuccess(response, uploadFile, uploadFiles, item)"
            :before-upload="beforeAvatarUpload" :accept="item.accept"
            v-if="(item?.maxUploads as number > item.value.length) || !item.maxUploads">
            <el-icon class="avatar-uploader-icon" :size="35" color="#999">
              <Plus />
            </el-icon>
          </el-upload>
        </div>
        <div v-if="item.styleType == 'slot'">
          <slot :name="item.key"></slot>
        </div>
      </el-form-item>
    </div>
    <el-form-item v-if="formData.btn?.length as number > 0">
      <el-button :type="v.type" @click="onClick(v)" v-for="v in formData.btn" :loading="loading || isLook">{{ v.text }}
      </el-button>
    </el-form-item>
  </el-form>
  <!-- 预览图片 -->
  <el-dialog v-model="dialogVisible">
    <div class="my-dialog-img">
      <img :src="dialogImageUrl" />
    </div>
  </el-dialog>
</template>
<script setup lang='ts'>
import { ref, getCurrentInstance, watch, computed } from 'vue'
import type { FormInstance, UploadFile, UploadFiles } from 'element-plus'
import { ElMessage, UploadProps } from 'element-plus'
import { ParentForm, SearchParam, ColumnBtnObj } from '@/interface/index'
import { useRouter } from 'vue-router'
import { useStore } from '@/store'
const store = useStore()
//监听加载
const loading = computed(() => {
  return store.getters['loading/getLoad']
})
const router = useRouter()
const { proxy } = getCurrentInstance() as any;
const ruleFormRef = ref<FormInstance>()
const isLook = ref<boolean>(false)//是否是查看状态
//搜索 父级传给子级 接口
interface PropsType {
  formData: ParentForm;
  isSetForm?: boolean;//触发表单重新赋值
  isSubmit?: boolean;//触发提交 关闭弹窗事件
  isClose?: boolean;//触发取消校验提示 关闭弹窗事件
  validateField?: string;//校验的字段
  validateFieldChange?: boolean;//触发校验事件
  isDialogVisible?: boolean;//弹窗变化
}
// 父传子 默认值
const props = withDefaults(defineProps<PropsType>(), {
  formData: () => ({
    formItem: [],
    size: 'default',
  })
});

const ruleForm = ref({})
//给表单赋值
const setForm = () => {
  props.formData?.formItem?.forEach((t: SearchParam) => {
    ruleForm.value[t.key] = t.value
  });
}
setForm()
//监听是否触发表单赋值
watch(
  () => props.isSetForm,
  () => {
    setForm()
  }
)
//监控弹窗变化
watch(
  () => props.isDialogVisible,
  () => {
    if (props.isDialogVisible) {
      setForm()//给表单赋值
      setTimeout(() => {
        proxy.$refs['ruleFormRef'].clearValidate()
      }, 10)
    }
  }
)
// 子传父 方法
const emit = defineEmits(['listenClick'])
//监听是否触发取消校验 关闭弹窗
watch(
  () => props.isClose,
  () => {
    onResetForm('isClose')
  }
)
//监听是否触发确定事件 关闭弹窗
watch(
  () => props.isSubmit,
  () => {
    onSubmitForm('isClose')
  }
)
//监听是否校验插槽字段
watch(
  () => props.validateFieldChange,
  () => {
    props.formData?.formItem?.forEach((t: SearchParam) => {
      if (t.key === props.validateField) {
        ruleForm.value[t.key] = t.value
      }
    });
    proxy.$refs['ruleFormRef'].validateField(props.validateField)
  }
)
//提交表单
const onSubmitForm = (flag?: string) => {
  store.commit('loading/setLoad', true)//加载中 防止暴击
  proxy.$refs['ruleFormRef'].validate((isValid: boolean) => {
    if (isValid) {
      emit('listenClick', 'listenMySubmit', ruleForm.value)
    } else {
      store.commit('loading/setLoad', false)
    }
  })
}
//取消提交
const onResetForm = (flag?: string) => {
  proxy.$refs['ruleFormRef'].clearValidate()
  if (flag === 'isClose') {
    //弹窗的时候点击的取消
    emit('listenClick', 'listenMyClose')
  } else {
    router.go(-1)
  }
}

//上传照片
//上传加载
const uploadLoading = ref<boolean>(false)
//上传之前校验
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  uploadLoading.value = true
  if (rawFile.size / 1024 / 1024 > 1) {
    ElMessage.error('图片不能超过 1MB!')
    uploadLoading.value = false
    return false
  }
  return true
}
//上传成功
const onSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles, val: SearchParam) => {
  if (response.code === 0) {
    if (val.styleType === "uploads") {
      //多图上传
      ruleForm.value[val.key].push(response.data.fileid)
    } else {
      ruleForm.value[val.key] = response.data.fileid
    }
    proxy.$refs['ruleFormRef'].validateField(val.key)
    ElMessage.success('图片上传成功!')
  }
  uploadLoading.value = false
}
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
//预览
const onPreview = (url: string) => {
  dialogImageUrl.value = url
  dialogVisible.value = !dialogVisible.value
}
//删除
const onDelete = (val: SearchParam, inx?: number) => {
  if (val.styleType === "uploads") {
    //多图上传
    ruleForm.value[val.key].splice(inx, 1)
  } else {
    ruleForm.value[val.key] = ''
  }
}
//按钮点击
const onClick = (val: ColumnBtnObj) => {
  if (val.name === 'myRouter') {
    //如果是跳转页面myRouter 走封装的跳转页面  
    router.push({ name: val.routerName })
  } else if (val.name === 'mySure') {
    //确定
    onSubmitForm()
  } else if (val.name === 'myCancel') {
    //取消
    onResetForm()
  } else {
    //其他不走封装方法的 抛出去给父级 处理
    emit('listenClick', val.name, ruleForm.value)
  }
}

</script>
<style scoped lang='scss'>
.my-dialog {
  &__box {
    max-height: 60vh;
    overflow-x: initial;
    overflow-y: auto;
  }
}
</style>
<style lang='scss'>
.el-dialog {
  border-radius: 6px !important;

  .el-dialog__header {
    border-radius: 6px 6px 0 0 !important;
    // background-color: #fff !important;
    margin-right: 0;
    padding: 10px 20px 0 20px;
    line-height: 44px;

    .el-dialog__title {
      font-size: 16px;
      font-weight: 600;
    }
  }

  .el-dialog__body {
    padding: 15px 20px;
  }

  .el-dialog__footer {
    // border-top: 1px solid #e8eaec !important;
    padding: 15px 20px;
  }

  .el-dialog__headerbtn {
    top: 0;
    right: 0;
    height: 54px;
    line-height: 54px;

    .el-dialog__close {
      color: #999;
      margin-top: 20px;
    }
  }
}

.my-upload {
  width: 120px;
  height: 120px;
  border: 1px solid $my-color-border;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  margin-right: 10px;
  overflow: hidden;
  position: relative;
  cursor: pointer;

  .avatar-uploader-icon {
    width: 120px;
    height: 120px;
  }

  &__img {
    width: 100%;
    height: 100%;
    display: block;
  }

  &__bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 120px;
    height: 120px;
    background: rgba($color: #000000, $alpha: 0.5);
    display: none;
    align-items: center;
    justify-content: center;

    .el-icon {
      margin: 0 5px;
      color: #fff;
    }
  }

  &:hover {
    .my-upload__bg {
      display: flex;
    }
  }
}

.my-dialog-img {
  width: 100%;
  height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;

  img {
    display: block;
    max-width: 100%;
    max-height: 100%;
  }
}
</style>